package br.com.petsis.funcionalidades.acessoCliente;

import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;

import nl.captcha.Captcha;
import nl.captcha.backgrounds.GradiatedBackgroundProducer;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.international.StatusMessage.Severity;

import br.com.petsis.entity.Cliente;
import br.com.petsis.entity.Perfil;
import br.com.petsis.entity.Pet;
import br.com.petsis.entity.Raca;
import br.com.petsis.entity.Usuario;
import br.com.petsis.enumerations.TipoOperacaoEnum;
import br.com.petsis.funcionalidades.auditoria.AuditoriaController;
import br.com.petsis.utilitarios.UtilMail;
import br.com.petsis.utilitarios.UtilString;

@Name("acessoClienteController")
@AutoCreate
@Scope(ScopeType.CONVERSATION)
public class AcessoClienteController {
	
	private static final String QRY_USUARIO_EMAIL = "select u from Usuario u where u.flgAtivo = 'T' and UPPER(u.cliente.dscEmail) = UPPER(:email)";
	private static final String QRY_RACAS = "select r from Raca r where r.flgAtivo = 'T'";
	private static final String PARAMETER_EMAIL = "email";

	@In(create=true)
	private EntityManager entityManager;
	
	private String email;
	
	private Cliente clienteEdicao;
	
	private List<Pet> listaPets;
	
	private List<Raca> listaRacas;
	
	private boolean selecionadoTodosPets;
	
	private String sessionKeyName;
	
	private String captcha;
	
	private String resposta;
	
	@In
	private AuditoriaController auditoriaController;
	
	public String getSessionKeyName() {
		return sessionKeyName;
	}

	public void setSessionKeyName(String sessionKeyName) {
		this.sessionKeyName = sessionKeyName;
	}

	public String getCaptcha() {
		return captcha;
	}

	public void setCaptcha(String captcha) {
		this.captcha = captcha;
	}

	public boolean isSelecionadoTodosPets() {
		return selecionadoTodosPets;
	}

	public void setSelecionadoTodosPets(boolean selecionadoTodosPets) {
		this.selecionadoTodosPets = selecionadoTodosPets;
	}

	public List<Pet> getListaPets() {
		if (listaPets == null) {
			listaPets = new ArrayList<Pet>();
		}
		return listaPets;
	}

	public void setListaPets(List<Pet> listaPets) {
		this.listaPets = listaPets;
	}
	
	public Cliente getClienteEdicao() {
		if (clienteEdicao == null) {
			clienteEdicao = new Cliente();
		}
		return clienteEdicao;
	}

	public void setClienteEdicao(Cliente clienteEdicao) {
		this.clienteEdicao = clienteEdicao;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}
	
	public List<Raca> getListaRacas() {
		if (listaRacas == null) {
			return entityManager.createQuery(QRY_RACAS).getResultList();
			/*List<Raca> racas = entityManager.createQuery(QRY_RACAS).getResultList();
			listaRacas = new ArrayList<SelectItem>();
			listaRacas.add(new SelectItem(null,"Selecione"));
			for(Raca r : racas){
				listaRacas.add(new SelectItem(r.getIdRaca(),r.getDscNome()));
			}*/
		}
		return listaRacas;
	}

	public void setListaRacas(List<Raca> listaRacas) {
		this.listaRacas = listaRacas;
	}
	
	public void selecionaTodosPets(){
		for(Pet c : getListaPets()){
			if(isSelecionadoTodosPets()){
				c.setSelecionado(true);
			}else{
				c.setSelecionado(false);
			}
		}
	}
	
	public void onLoad(){
		setEmail(null);
		setCaptcha(null);
	}

	/**
	 * Valida se o e-mail informado pelo cliente já existe na base de dados
	 * 
	 * @param email
	 * @return [TRUE] O e-mail é novo no sistema [FALSE] O e-mail já está sendo utilizado por outro cliente
	 */
	public boolean validarEmailCliente(String email){
		try{
			entityManager.createQuery("select c from Cliente c where UPPER(c.dscEmail) = UPPER(:email)")
				.setParameter(PARAMETER_EMAIL, email)
				.getSingleResult();
			return false;
		}catch(NoResultException e){
			return true;
		}
	}
	
	public void salvarNovoCliente(){
		if(!validaCaptcha()){
			return;
		}
		if((getClienteEdicao().getTelCelular() == null || getClienteEdicao().getTelCelular().isEmpty()) &&
				(getClienteEdicao().getTelResidencial() == null || getClienteEdicao().getTelResidencial().isEmpty())){
			FacesMessages.instance().add(Severity.ERROR,"Informe pelo menos um telefone.");
			return;
		}
		if(!validarEmailCliente(clienteEdicao.getDscEmail())){
			FacesMessages.instance().add(Severity.ERROR,"O e-mail informado já encontra-se cadastrado. Acesse o link 'Esqueci minha senha' ou entre em contato conosco.");
			return;
		}
		
		if(recuperaPerfilCliente() == null){
			FacesMessages.instance().add(Severity.INFO,"Perfil de CLIENTE ainda não cadastrado. Entre em contato com o administrador do sistema.");
			return;
		}
		
		clienteEdicao.setFlgAtivo('T');
		Cliente clienteSalvo = entityManager.merge(clienteEdicao);
		
		for(Pet p : listaPets){
			if(p.getIdRacaSelecionada() == null){
				FacesMessages.instance().add(Severity.ERROR,"Raça não encontrada. Favor, tente novamente.");
				return;
			}
			if(p.getDscNome() == null || p.getDscNome().isEmpty()){
				continue;
			}
			Raca novaRaca = entityManager.find(Raca.class, p.getIdRacaSelecionada());
			p.setRaca(null);
			p.setRaca(novaRaca);
			p.setCliente(clienteSalvo);
			p.setPorte('P');
			p.setFlgAtivo('T');
			
			Pet petSalvo = entityManager.merge(p);
		}
		Usuario usuario = new Usuario();
		usuario.setCliente(clienteSalvo);
		usuario.setDscNome(clienteSalvo.getDscNome());
		usuario.setDscUsuario(clienteSalvo.getDscNome().length() >= 50 ? clienteSalvo.getDscNome().substring(0,50) : clienteSalvo.getDscNome());
		usuario.setFlgAtivo('T');
		usuario.setDtaUltimoAcesso(null);
		usuario.setPerfil(recuperaPerfilCliente());
		String senha = gerarNovaSenha();
		usuario.setDscSenha(UtilString.md5(senha));
		Usuario usuarioSalvo = entityManager.merge(usuario);
		
		entityManager.flush();
		enviarEmailNovaSenha(clienteSalvo.getDscEmail(), senha);
		enviarEmailNotificacao();
		listaPets = new ArrayList<Pet>();
		clienteEdicao = new Cliente();
		FacesMessages.instance().add(Severity.INFO,"Cliente salvo com sucesso.");
	}
	
	public void enviarEmailNotificacao(){
    	SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm");
    	StringBuilder texto = new StringBuilder();
    	texto.append("<center><img src=\"cid:image\"><br/>");
    	texto.append("<b>Atenção</b><br/>");
    	texto.append("Um novo cliente cadastrou-se no sistema.<br/><br/>Detalhes:<br/><table>");
    	texto.append("<tr><td><b>Cliente:</b></td><td> ");
    	texto.append(getClienteEdicao().getDscNome());
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>E-mail:</b></td><td> ");
    	texto.append(getClienteEdicao().getDscEmail());
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>Data de cadastramento:</b></td><td> ");
    	texto.append(sdf.format(new Date()));
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>Telefone(s):</b></td><td> ");
    	texto.append(getClienteEdicao().getTelCelular());
    	texto.append("/");
    	texto.append(getClienteEdicao().getTelResidencial());
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>Endereço:</b></td><td> ");
    	texto.append(getClienteEdicao().getDscEndereco());
    	texto.append(", ");
    	texto.append(getClienteEdicao().getDscCidade());
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>Pet(s):</b></td><td> ");
    	for (Pet pet : listaPets) {
    		texto.append(pet.getDscNome());
    		texto.append(" - ");
    		texto.append(pet.getRaca().getDscNome());
    		texto.append("<br/>");
		}
    	texto.append("</td></tr></table>");
    	texto.append("<br/><br/><br/>Sistema Petit Ami");
		texto.append("<br/>Contato: (61) 3301-1465</center>");
    	
    	String assunto = "PETIT AMI: Novo cliente cadastrado no sistema";
    	
    	try {
			UtilMail.enviarEmail(texto.toString(), UtilMail.EMAIL_PADRAO_PET, assunto);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
    }
	
	public void novoPet(){
		getListaPets().add(new Pet(new Raca()));
	}
	
	public Perfil recuperaPerfilCliente(){
		try{
			return (Perfil)entityManager.createQuery("select p from Perfil p where UPPER(p.dscNome) like UPPER(:nome)")
				.setParameter("nome", "cliente")
				.getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public void excluirPet(){
		List<Pet> listaRemocao = new ArrayList<Pet>();
		for(Pet c : getListaPets()){
			if(c.isSelecionado()){
				if(c.getIdPet() != null){
					c.setFlgAtivo('F');
					entityManager.merge(c);
				}
				listaRemocao.add(c);
			}
		}
		entityManager.flush();
		getListaPets().removeAll(listaRemocao);
		setSelecionadoTodosPets(false);
	}
	
	public List<Raca> autocomplete(Object suggest) {
        String pref = (String)suggest;
        List<Raca> result = new ArrayList<Raca>();

        Iterator<Raca> iterator = getListaRacas().iterator();
        while (iterator.hasNext()) {
            Raca elem = ((Raca) iterator.next());
            if ((elem.getDscNome() != null && elem.getDscNome().toLowerCase().indexOf(pref.toLowerCase()) == 0) || "".equals(pref))
            {
                result.add(elem);
            }
        }
        return result;
	}
	
	public boolean validaCaptcha(){
//		Captcha captchaValue = UtilString.getSessionKeyValueCaptcha();
		
		if(!resposta.equalsIgnoreCase(getCaptcha())){
			FacesMessages.instance().add(Severity.ERROR,"Código de validação inválido.");
//			reCaptcha();
			return false;
		}
		return true;
	}
	
	public void enviarSenha(){
		if(!validaCaptcha()){
			return;
		}
		try{
			Usuario usuario = (Usuario)entityManager.createQuery(QRY_USUARIO_EMAIL)
				.setParameter(PARAMETER_EMAIL, getEmail())
				.getSingleResult();
			String novaSenha = gerarNovaSenha();
			usuario.setDscSenha(UtilString.md5(novaSenha));
			usuario.setDtaUltimoAcesso(null);
			entityManager.merge(usuario);
			entityManager.flush();
			enviarEmailNovaSenha(getEmail(), novaSenha);
		}catch(NoResultException e){
			FacesMessages.instance().add(Severity.ERROR,"O e-mail informado não consta em nosso sistema. Caso você já seja nosso cliente, entre em contato com o nosso atendimento. Caso seja novo cliente, clique no link de 'novos clientes'.");
			return;
		}
	}
	
	public String gerarNovaSenha(){
		Long i = (long) (10000000 + Math.random() * 8999999l);
		return i.toString();
	}
	
	public void enviarEmailNovaSenha(String destinatario, String novaSenha){
		try {
			StringBuilder texto = new StringBuilder();
			texto.append("<center><img src=\"cid:image\">");
			texto.append("<br/><br/><b>Este é um e-mail automático, por favor não responda.</b><br/>");
			texto.append("<br/><br/>Sua nova senha de acesso à área do cliente Petit Ami é:");
			texto.append(novaSenha);
			texto.append("<br/><br/><u>Obs: Altere a sua senha no primeiro acesso.</u>");
			texto.append("<br/><br/><br/>Sistema Petit Ami");
			texto.append("<br/>Contato: (61) 3301-1465</center>");
			UtilMail.enviarEmail(texto.toString(), destinatario, "PETIT AMI: RECUPERAÇÃO DE SENHA.");
			FacesMessages.instance().add(Severity.INFO,"Foi enviado um e-mail contendo a nova senha.");
		} catch (Exception e) {
			FacesMessages.instance().add(Severity.ERROR,"Não foi possível enviar o e-mail com a nova senha. Verifique o e-mail informado ou tente novamente mais tarde.");
			e.printStackTrace();
		}
	}
	
	public static void reCaptcha(){
		/*StickyCaptchaServlet captchaServlet = new StickyCaptchaServlet();
		
		HttpServletRequest req = (HttpServletRequest) FacesContext
        	.getCurrentInstance().getExternalContext().getRequest();

		HttpServletResponse resp = (HttpServletResponse) FacesContext
			.getCurrentInstance().getExternalContext().getResponse();
        
	    try {
	    	captchaServlet.doGet(req, resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
	
	    FacesContext.getCurrentInstance().responseComplete();*/
	}
	
	public byte[] recuperaImagemCaptcha(){
		Captcha captcha = new Captcha.Builder(200, 60)
	        .addText()
	        .addBackground(new GradiatedBackgroundProducer(Color.WHITE, Color.WHITE))
	        .gimp()
//	        .addNoise()
//	        .addBorder()
	        .build();
		resposta = captcha.getAnswer();
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ImageIO.write( captcha.getImage(), "jpg", baos );
			baos.flush();
			byte[] imageInByte = baos.toByteArray();
			baos.close();
			return imageInByte;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}
